import jwt from 'jsonwebtoken';
import crypto from 'node:crypto';
import { tokenSecretKeyMap } from './clientMap';
import { type IncomingHttpHeaders } from 'node:http';
import { type User_Token_info } from './types';

const generateUserId = (): string => {
  const timestamp = Date.now().toString().slice(0, 10);
  const randomNum = Math.floor(Math.random() * 1000000)
    .toString()
    .padStart(6, '0');
  return timestamp + randomNum;
};

/**
 * 使用给定的盐值生成密码哈希
 * @param password - 用户原始密码
 * @param salt - 加密盐值
 * @returns 生成的密码哈希值
 */
const getPasswordHash = (password: string, salt: string) => {
  return `${crypto
    .pbkdf2Sync(password, salt, 10000, 32, 'sha512')
    .toString('hex')}`;
};

/**
 * 生成随机字符串
 * @param length - 随机字符串长度
 * @returns 随机字符串
 */
const getRadomString = (length: number) => {
  return crypto.randomBytes(length).toString('hex');
};

const verifyToken = async (
  token: string,
  clientId: string
): Promise<boolean> => {
  try {
    const secretKey = getSecretKey(token);
    if (secretKey === '') {
      console.error('无法获取token密钥');
      return false;
    }
    const decrypted: User_Token_info = await new Promise((resolve, reject) => {
      jwt.verify(token, secretKey, (err, decoded) => {
        if (err) {
          console.error('token解密错误：', err);
          reject(false);
        } else {
          resolve(decoded as User_Token_info);
        }
      });
    });

    if (decrypted.clientId !== clientId) {
      console.error('客户端与token不匹配');
      return false;
    }

    return true;
  } catch (error) {
    return false;
  }
};

const getSecretKey = (token: string): string => {
  const secretKey = tokenSecretKeyMap.get(token);
  if (typeof secretKey !== 'string') {
    return '';
  }
  return secretKey;
};

/**
 * 验证请求头参数
 * @param header 请求头
 * @param headParam 请求头参数名
 * @returns  返回请求头内容
 */
const verifyHeaderParam = (
  header: IncomingHttpHeaders,
  paramName: string,
  type: 'string' | 'number' | 'object'
): boolean => {
  if (!header.hasOwnProperty(paramName)) {
    return false;
  }
  if (typeof header[paramName] !== type || !header[paramName]) {
    return false;
  }
  return true;
};

const verifyRequestParam = (
  requestBody: any,
  paramName: string,
  type: 'string' | 'number' | 'object'
) => {
  if (!requestBody.hasOwnProperty(paramName)) {
    return false;
  }
  if (typeof requestBody[paramName] !== type || !requestBody[paramName]) {
    return false;
  }
  return true;
};

/**
 * 验证登录状态
 * @param header 请求头
 * @returns 验证结果
 */
const verifyLoginStatus = async (
  header: IncomingHttpHeaders
): Promise<boolean> => {
  if (!verifyHeaderParam(header, 'authorization', 'string')) {
    return false;
  }
  if (!verifyHeaderParam(header, 'x-device-id', 'string')) {
    return false;
  }
  const token = header['authorization'] as string;
  const clientId = header['x-device-id'] as string;

  if (!(await verifyToken(token, clientId))) {
    return false;
  }

  return true;
};

/**
 * 从token中获取用户信息
 * @param header 请求头
 * @returns 用户信息
 */
const getUserInfo = async (
  token: string
): Promise<User_Token_info | undefined> => {
  const secretKey = getSecretKey(token);
  if (secretKey === '') {
    return void 0;
  }
  const decrypted: User_Token_info = await new Promise((resolve, reject) => {
    jwt.verify(token, secretKey, (err, decoded) => {
      if (err) {
        console.error('token解密错误：', err);
        reject(false);
      } else {
        resolve(decoded as User_Token_info);
      }
    });
  });

  return decrypted;
};

export default {
  getPasswordHash,
  getRadomString,
  verifyToken,
  getSecretKey,
  verifyHeaderParam,
  verifyRequestParam,
  verifyLoginStatus,
  getUserInfo,
  generateUserId
};
